#-------------------------------------------------------------------------------
# Name:    powercuvre
# Purpose: Provides a PowerCurve class which can convert wind speed and direction 
#          into power.  Power curves are specified by direction. 
#          Uses 2D linear interpolation  between speed and direction points. 
#
# Author:    sam.hawkins@vattenfall.com
#
# TODO: work out the behaviour of the bivariate spline, the shape of arrays
#       it returns are unusual.
#
#
# Created:     12/07/2012
# Copyright:   (c) slha 2012
# Licence:     <your licence>
#-------------------------------------------------------------------------------
#!/usr/bin/env python


import numpy as np
from scipy import interpolate

#
# Import these if you need plotting.
# can comment them out on platforms 
# which don;t have them.
#
from matplotlib import pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
#import pylab as p
#from mpl_toolkits.mplot3d.axes3d import get_test_data


def main():
    test()

class PowerCurve(object):
    """Represents a power curve, provides power(speed, direction) method to convert
    wind speed and direction into power """

    def __init__(self, scentres, dcentres, pcentres):
        """
        Creates a PowerCurve with a RectBivariateSpline to linearly interpolate power
        from speed and direction

        Arguments:
            scentres -- centre of speed bins
            dcentres -- direction bin centres
            pcentres -- array of shape[size(scentres), size(dcentres)] giving power by speed and direction"""

        if pcentres.shape != (scentres.shape[0], dcentres.shape[0]):
            raise Exception('power should be of size [scentres.shape[0], dcentres.shape[0]]')

        self._scentres = scentres
        self._dcentres = dcentres
        self._pcentres = pcentres
        self._spline   = interpolate.RectBivariateSpline(scentres, dcentres, pcentres, kx=1, ky=1, s=0)

    def power(self, speed, direction):
        return self._spline(speed, direction)

    def tofile(self, filename):
        """ Write a textual repesenation of PowerCurve"""
        f = open(filename, 'w')

        #
        # TODO
        # Only write basics for now, add any headers later
        # Which orientation to we write to?
        #
        # pcentres(speed, direction)
        #
        f.write('0.0,')
        drow = ','.join(map(str, self._scentres))
        f.write(drow)
        f.write('\n')
        for j in range(self._dcentres.shape[0]):
            f.write('%s,' % self._dcentres[j])
            row = ','.join(map(str, self._pcentres[:, j]))
            f.write(row)
            f.write('\n')
        f.close()


def from_file(filename):
    """ Creates a PowerCurve from a text file. Format of the text 
    is row 0 = speed centre points, 
       col 0 = direction centre points
       everything else = power"""
    
    data = np.loadtxt(filename, delimiter=',')

    scentres = data[0, 1:]
    dcentres = data[1:, 0]
    pcentres = data[1:, 1:].T

    pcurve = PowerCurve(scentres, dcentres, pcentres)
    return pcurve


##    f = open(filename, 'r')
##    tokens   = [l.split(',') for l in f.read().split('\n')]
##    data     = map(float, )
##    scentres = map(float, tokens[0][1:])
##    print scentres




def test():

    pcurve = from_file('UTH.csv')
    fig = plt.figure()
    ax = fig.gca(projection='3d')

    xs = pcurve._scentres
    ys = pcurve._dcentres
    zs = pcurve._pcentres
    
    X, Y = np.meshgrid(xs, ys)
    Z    = zs.T
    ax.plot_wireframe(X, Y, Z, rstride=3, cstride=3)

    #
    # Interpolate some points, including some which are off the
    # scale. Extraplation is done, be sure you want this!
    #
    spoints = [1,   5,  10,  20,  25]
    dpoints = [70, 180, 275, 350, 500]


    xpoints = spoints
    ypoints = dpoints
    zpoints = pcurve.power(xpoints, ypoints)[:, 0]

    ax.scatter(xpoints, ypoints, zpoints, 's')
    plt.show()


if __name__ == '__main__':
    main()
